package flex.cc.order.manage.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import flex.cc.PubUtils;
import flex.cc.PublicUtil;
import flex.cc.basicinformation.entity.ChannelDataEntity;
import flex.cc.basicinformation.entity.ChannelEntity;
import flex.cc.basicinformation.service.ChannelService;
import flex.cc.common.Constants;
import flex.cc.common.utils.HttpClientUtil;
import flex.cc.order.manage.dao.OrderServiceProviderDao;
import flex.cc.order.manage.dao.OrderTrackDao;
import flex.cc.order.manage.dto.order.OrderMainEntity;
import flex.cc.order.manage.dto.order.OrderTrackEntity;
import flex.cc.order.manage.model.CancelNoticeModel;
import flex.cc.order.manage.service.CancelNoticeService;
import flex.cc.order.manage.service.OrderMainService;
import flex.cc.system.dao.DictCodeDao;
import flex.cc.util.EncryptionDecryption;


@Service("cancelNoticeService")
@Transactional(rollbackFor = Exception.class)
public class CancelNoticeServiceImpl implements CancelNoticeService {
	private static final Logger logger = LoggerFactory.getLogger(CancelNoticeServiceImpl.class);
	
	@Resource
    private OrderTrackDao orderTrackDao;
	@Resource
	private OrderMainService orderMainService;
	@Resource
	private ChannelService channelService;
    @Resource
	private DictCodeDao dictCodeDao;
	@Resource
	private OrderServiceProviderDao orderServiceProviderDao;
	@Value("${api.config.partnercode}")
    private String partnercode;
	@Value("${api.config.clientid}")
    private String clientid;
	
    /**
     * @description 调用上游取消通知接口
     * @param requestBodyMap 请求体内容
     * @return
     * @exception/throws
    */
	@Override
	public String cancelNotice(CancelNoticeModel cancelNoticeModel) {
		String msg = "";
        //救援单号
        String ownerOrderNo = cancelNoticeModel.getOwnerOrderNo();
        //救援状态
        String salvationStatus = cancelNoticeModel.getSalvationStatus();
        //实际救援服务金额
        String serviceAmount = cancelNoticeModel.getServiceAmount();
        //取消备注
        String cancelReason = cancelNoticeModel.getCancelReason();
        //取消时间：yyyy-MM-dd HH:mm:ss
        String cancelTime = cancelNoticeModel.getCancelTime();
        //取消状态说明
        String cancelMsg = cancelNoticeModel.getCancelMsg();
        //取消状态代码
        String cancelCode = cancelNoticeModel.getCancelCode();
        //预计总行程距离（单位：m）
        String totalDistance = cancelNoticeModel.getTotalDistance();
        //已行驶距离（单位：m）
        String usedDistance = cancelNoticeModel.getUsedDistance();
        //已用时间，保司请求下单接口的请求时间至取消发起时间点（单位：秒）
        String elapsedTime = cancelNoticeModel.getElapsedTime();
        
		Map<String, Object> body = new HashMap<String, Object>();
		Map<String, String> requestHeader = new HashMap<String, String>();
		Map<String, String> requestBody = new HashMap<String, String>();
		requestHeader.put("partnerCode", partnercode);
		requestHeader.put("clientId", clientid);
		requestHeader.put("requestCode", "RescuerRequestCancel");
		requestBody.put("ownerOrderNo", ownerOrderNo);
		requestBody.put("salvationStatus", salvationStatus);
		requestBody.put("serviceAmount", serviceAmount);
		requestBody.put("cancelReason", cancelReason);
		requestBody.put("cancelTime", cancelTime);
		requestBody.put("cancelMsg", cancelMsg);
		requestBody.put("cancelCode", cancelCode);
		requestBody.put("totalDistance", totalDistance);
		requestBody.put("usedDistance", usedDistance);
		requestBody.put("elapsedTime", elapsedTime);
		
		body.put("requestHeader", requestHeader);
		body.put("requestBody", requestBody);
		AtomicReference<Integer> counter = new AtomicReference<Integer>(0);
		while(counter.get()<3){
			try {
				logger.info("取消通知接口第" + (counter.get()+1) + "次请求");
				EncryptionDecryption des = new EncryptionDecryption();
				String jsonStr = JSON.toJSONString(body);
				logger.info("取消通知接口加密前的请求报文=" + jsonStr);
				String jsonBody = des.encrypt(jsonStr);
				logger.info("取消通知接口加密后的请求报文=" + jsonBody);
				
				//根据clientId去查渠道商信息
				Map<String, String> channelMap = new HashMap<>();
				channelMap.put("clientId", cancelNoticeModel.getSourceName());
				List<ChannelEntity> channelList = channelService.findChannelByParam(channelMap);
				if(channelList.size()==0 || channelList==null){
					msg = "未找到渠道商";
					return msg;
				}
				String channelId = channelList.get(0).getId().toString();
				List<ChannelDataEntity> channelDataList = channelService.queryListByYwId(channelId);
				String cancelNoticeUrl = "";
				for(int i=0; i<channelDataList.size(); i++){
		    		if(Constants.cancelRescue.equals(channelDataList.get(i).getUrlType())){
		    			cancelNoticeUrl = channelDataList.get(i).getUrl();
		    			break;
		    		}
		    	}
				if(PublicUtil.isEmpty(cancelNoticeUrl)){
					msg = "渠道商取消通知接口地址未配置";
					insertCancelTrack(cancelNoticeModel,"回调上游取消通知失败，"+msg);
					return msg;
				}
				
				String result = HttpClientUtil.sendHttpPost(cancelNoticeUrl, jsonBody, null);
				logger.info("取消通知接口返回响应加密报文=" + result);
				if(result == null || "".equals(result)){
					counter.getAndSet(5);
					msg = "上游取消通知接口返回报文为空";
					//插入轨迹信息
					insertCancelTrack(cancelNoticeModel,"回调上游取消通知失败，"+msg);
					return msg;
				}
				result = des.decrypt(result.trim(), "UTF-8");
				logger.info("取消通知接口返回响应报文解密=" + result);
				JSONObject json = JSONObject.parseObject(result);
		        String code =  json.get("responseCode").toString();
		        if("00".equals(code)){ //00
		        	msg = "成功";
		        	counter.getAndSet(5);
					//插入轨迹信息
		        	insertCancelTrack(cancelNoticeModel,"回调上游取消通知成功，备注"+cancelReason);
				}else{
					if(counter.get()==2){
						msg = "失败";
						counter.getAndSet(5);
						//插入轨迹信息
						insertCancelTrack(cancelNoticeModel,"回调上游取消通知失败");
					}else{
						counter.compareAndSet(counter.get(), counter.get()+1);
					}
		        }
			} catch (Exception e) {
				logger.info("请求上游取消通知接口异常    "+e.getMessage());
				msg = "请求上游取消通知接口异常";
				counter.getAndSet(5);
				//插入轨迹信息
				insertCancelTrack(cancelNoticeModel,"回调上游取消通知异常");
			}
		}
		return msg;
	}

	//2022年1月4日 下午2:12:38  保存取消通知轨迹记录
	//flag：0:成功标识，1:失败标识
	public void insertCancelTrack(CancelNoticeModel cancelNoticeModel,String trackDesc) {
		logger.info("取消通知接口轨迹描述=" + trackDesc);
		Map<String, Object> order_param = new HashMap<>();
		order_param.put("ownerOrderNo", cancelNoticeModel.getOwnerOrderNo());
		OrderMainEntity orderMain = orderMainService.getOneByParams(order_param);
		
		OrderTrackEntity vo = new OrderTrackEntity();
		vo.setDataId(PubUtils.uuid());
		vo.setOrderNo(orderMain.getOrderNo());
		vo.setTrackType("03"); // 轨迹类型：下单备注00、救援轨迹01、催单备注02、取消备注03，用于区分备注轨迹还是救援轨迹
		vo.setTrackDesc(trackDesc);// 轨迹描述：下单备注内容、救援轨迹描述、催单接口的催单内容、取消接口的取消原因
		// 以下两个字段，上游到下游可以为空，下游到上游，需赋值，用于计算是否为延时单和轨迹展示
		vo.setStatus(orderMain.getStatus()); // 服务单主表的状态码
		Map<String, Object> dictParams = new HashMap<>();
		dictParams.put("typeCode", "orderStatus");
		dictParams.put("code", orderMain.getStatus());
		vo.setServiceStatus("服务取消");
		vo.setCreateTime(new Date());
		vo.setUpdateTime(new Date());
		vo.setCreater(cancelNoticeModel.getCreater());
		vo.setUpdater(cancelNoticeModel.getUpdater());
		vo.setIsDelete(0);
		logger.info("取消通知接口轨迹描述=" + vo.getTrackDesc());
		orderTrackDao.insert(vo);
	}
}
